package com.king.wx.http;

import com.google.common.io.ByteStreams;
import org.apache.http.*;
import org.apache.http.client.CookieStore;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.SystemDefaultRoutePlanner;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.ProxySelector;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * HttpClient工具类
 */
public final class HttpClientUtil {

    private final CloseableHttpClient httpClient;

    private final CookieStore cookieStore;

    private static final int TIME_OUT = 60 * 1000;

    public HttpClientUtil() {

        RedirectStrategy redirectStrategy = new RedirectStrategy() {	//设置重定向处理方式
            @Override
            public boolean isRedirected(HttpRequest arg0, HttpResponse arg1, HttpContext arg2)
                    throws ProtocolException {

                return false;
            }

            @Override
            public HttpUriRequest getRedirect(HttpRequest arg0, HttpResponse arg1, HttpContext arg2)
                    throws ProtocolException {

                return null;
            }
        };
        cookieStore = new BasicCookieStore();

        SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(ProxySelector.getDefault());
        httpClient = HttpClients.custom().setRoutePlanner(routePlanner).setDefaultCookieStore(cookieStore).setRedirectStrategy(redirectStrategy).build();
    }

    private void config(HttpRequestBase httpRequestBase) {
        // 设置Header等
        // httpRequestBase.setHeader("User-Agent", "Mozilla/5.0");
        // httpRequestBase.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
        // httpRequestBase.setHeader("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");// "en-US,en;q=0.5");
        // httpRequestBase.setHeader("Accept-Charset", "ISO-8859-1,utf-8,gbk,gb2312;q=0.7,*;q=0.7");

        // 配置请求的超时设置
        httpRequestBase.setConfig(RequestConfig.custom()
                .setConnectionRequestTimeout(TIME_OUT)
                .setConnectTimeout(TIME_OUT)
                .setSocketTimeout(TIME_OUT)
                .build());
    }

    private void setPostParams(HttpPost httpost, Map<String, Object> params) {
        List<NameValuePair> nvps = new ArrayList<>();
        Set<String> keySet = params.keySet();
        for (String key : keySet) {
            nvps.add(new BasicNameValuePair(key, params.get(key).toString()));
        }
        try {
            httpost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    private void setPostParams(HttpPost httpost, String strBody) {
        httpost.setEntity(new StringEntity(strBody, "UTF-8"));
    }

    public String getCookieVal(String name) {
        List<Cookie> cookieList =  cookieStore.getCookies();
        for (Cookie cookie : cookieList) {
            if (cookie.getName().equals(name)) {
                return cookie.getValue();
            }
        }
        return null;
    }

    /**
     * POST请求URL获取内容
     *
     * @param url
     * @return
     * @author SHANHY
     * @throws IOException
     * @create 2015年12月18日
     */
    public String post(String url, String body) {
        HttpPost httppost = new HttpPost(url);
        config(httppost);
        setPostParams(httppost, body);
        return execute(httppost);
    }

    public String postFile(String url, String filePath, Map<String, String> params) {
        HttpPost httpPost = new HttpPost(url);
        config(httpPost);
        setPostFileParams(httpPost, params, filePath);
        return execute(httpPost);
    }

    private void setPostFileParams(HttpPost httpPost, Map<String, String> params, String filePath) {

        File file = new File(filePath);

        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        for (String key : params.keySet()) {
            multipartEntityBuilder.addTextBody(key, params.get(key));
        }

        multipartEntityBuilder.addBinaryBody("filename", file);
        httpPost.setEntity(multipartEntityBuilder.build());
    }

    /**
     * POST请求URL获取内容
     * 
     * @param url
     * @return
     * @author SHANHY
     * @throws IOException 
     * @create 2015年12月18日
     */
    public String post(String url, Map<String, Object> params) {
        HttpPost httppost = new HttpPost(url);
        config(httppost);
        setPostParams(httppost, params);
        return execute(httppost);
    }

    /**
     * GET请求URL获取内容
     * 
     * @param url
     * @return
     * @author SHANHY
     * @create 2015年12月18日
     */
    public String get(String url) {
        HttpGet httpget = new HttpGet(url);
        config(httpget);
        return execute(httpget);
    }

    /**
     * GET请求URL获取文件
     *
     * @param url
     * @return
     * @author SHANHY
     * @create 2015年12月18日
     */
    public byte[] getFile(String url) {
        HttpGet httpget = new HttpGet(url);
        config(httpget);
        return executeFile(httpget);
    }

    private byte[] executeFile(HttpUriRequest request) {
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(request,HttpClientContext.create());
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                byte[] result = ByteStreams.toByteArray(entity.getContent());
                EntityUtils.consume(entity);
                return result;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null)
                    response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private String execute(HttpUriRequest request) {
        CloseableHttpResponse response = null;
        try {
            response = httpClient.execute(request,HttpClientContext.create());
            HttpEntity entity = response.getEntity();
            String result = EntityUtils.toString(entity, "UTF-8");
            EntityUtils.consume(entity);
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null)
                    response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}